/*
 *
 *  Copyright (C) 2012-2024
 *  All rights reserved, Designed By 杭州连线客信息技术有限公司
 *  注意：
 *  本软件为杭州连线客信息技术有限公司开发研制，未经购买不得使用
 *  购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 *  一经发现盗用、分享等行为，将追究法律责任，后果自负
 *
 */

package com.lxk.oms.flow.order;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.lxk.oms.order.domain.req.CreateOrderReq;
import com.lxk.service.core.Result;
import com.lxk.service.pms.api.PmsServiceApi;
import com.lxk.service.pms.response.PmsProductSkuDto;
import com.lxk.service.pms.response.PmsProductSpuDto;
import com.lxk.service.ums.api.UmsServiceApi;
import com.lxk.service.ums.request.QueryUserAddressParam;
import com.lxk.service.ums.response.UmsUserAddressResponse;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.core.NodeComponent;
import com.yomahub.liteflow.log.LFLog;
import com.yomahub.liteflow.log.LFLoggerManager;
import lombok.AllArgsConstructor;
import org.dromara.common.core.exception.ServiceException;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单上下文填充
 *
 * @author heyi
 * 2024/8/20
 */
@LiteflowComponent(value = FlowOrderNodeConst.FILL_NEED_STOCK_PARAM_CREATE_ORDER)
@AllArgsConstructor
public class OrderFillNeedStockContextNode extends NodeComponent {
    private final LFLog log = LFLoggerManager.getLogger(FlowExecutor.class);
    private final UmsServiceApi umsServiceApi;
    private final PmsServiceApi pmsServiceApi;


    @Override
    public void process() throws Exception {
        CreateOrderReq params = this.getRequestData();
        log.info("下单参数:{}", params);
        Long merId = params.getMerId();
        OrderContext context = this.getContextBean(OrderContext.class);
        Long userId = context.getUserId();
        // 设置SKU信息
        fillSkuInfo(params, merId, context);
        context.setOrderItemBoList(new ArrayList<>());
        // 设置地址信息
        fillAddress(userId, params, context);
        context.setDeliveryType(params.getDeliveryType());
        // 订单名字最大为200，超过后截取前200
        context.setOrderName(StrUtil.subWithLength(params.getOrderName(), 0, 200));
        context.setCreateType(params.getCreateType());
    }


    @Override
    public boolean isAccess() {
        OrderContext context = this.getContextBean(OrderContext.class);
        return context.getNeedStock();
    }

    /**
     * 设置地址信息
     *
     * @param userId
     * @param params
     * @param context
     */
    private void fillAddress(Long userId, CreateOrderReq params, OrderContext context) {
        Result<UmsUserAddressResponse> userAddress = umsServiceApi.queryUserAddress(new QueryUserAddressParam().setUserId(userId).setId(params.getUserAddressId()));
        if (userAddress.isFail()) {
            throw new ServiceException(userAddress.getMsg());
        }
        UmsUserAddressResponse data = userAddress.getData();
        context.setOrderCityName(data.getCity());
        context.setOrderCityId(data.getCityId());
        context.setOrderProvinceId(data.getProvinceId());
        context.setOrderProvinceName(data.getProvince());
        context.setOrderDistrictId(data.getDistrictId());
        context.setOrderDistrictName(data.getDistrict());
        context.setReceiverDetailAddress(data.getDetail());
        context.setReceiverName(data.getRealName());
        context.setReceiverMobile(data.getPhone());
    }

    /**
     * 设置SKU信息
     *
     * @param params
     * @param merId
     * @param context
     */
    private void fillSkuInfo(CreateOrderReq params, Long merId, OrderContext context) {
        List<CreateOrderReq.CreateOrderItem> createOrderItemList = params.getCreateOrderItemList();
        // 合并SKU
        Map<Long, List<CreateOrderReq.CreateOrderItem>> skuMap =
            createOrderItemList.stream().collect(Collectors.groupingBy(CreateOrderReq.CreateOrderItem::getSkuId));
        Set<Long> skuIdSet = skuMap.keySet();
        // 批量获取SKU信息
        Result<List<PmsProductSkuDto>> skuList = pmsServiceApi.queryBySkuIdList(CollUtil.newArrayList(skuIdSet));
        if (skuList.isFail()) {
            throw new ServiceException(skuList.getMsg());
        }
        if (CollUtil.isEmpty(skuList.getData())) {
            throw new ServiceException("商品规格未找到");
        }
        List<PmsProductSkuDto> skuListData = skuList.getData();
        // 转化SKU—MAP
        Map<Long, List<PmsProductSkuDto>> skuInfoMap = skuListData.stream().collect(Collectors.groupingBy(PmsProductSkuDto::getId));
        // SPU
        Set<Long> spuIdSet = skuListData.stream().map(PmsProductSkuDto::getSpuId).collect(Collectors.toSet());
        Result<List<PmsProductSpuDto>> spuList = pmsServiceApi.queryBySpuIdList(CollUtil.newArrayList(spuIdSet), false);
        if (spuList.isFail()) {
            throw new ServiceException(spuList.getMsg());
        }
        if (CollUtil.isEmpty(spuList.getData())) {
            throw new ServiceException("商品未找到");
        }
        List<PmsProductSpuDto> spuListData = spuList.getData();
        Map<Long, PmsProductSpuDto> spuMap = spuListData.stream().collect(Collectors.toMap(PmsProductSpuDto::getId, v -> v));
        // 设置SKU信息
        List<OrderContext.SkuInfo> skuInfoList = buildSkuList(merId, skuMap, skuInfoMap, spuMap);
        context.setSkuInfoList(skuInfoList);
    }

    /**
     * 构建SKU集合
     *
     * @param merId
     * @param skuMap
     * @param skuInfoMap
     * @param spuMap
     * @return
     */
    private List<OrderContext.SkuInfo> buildSkuList(Long merId, Map<Long, List<CreateOrderReq.CreateOrderItem>> skuMap, Map<Long, List<PmsProductSkuDto>> skuInfoMap, Map<Long, PmsProductSpuDto> spuMap) {
        return skuMap.entrySet().stream().map(sku -> {
            Long skuId = sku.getKey();
            List<CreateOrderReq.CreateOrderItem> skuValue = sku.getValue();
            List<PmsProductSkuDto> productSkuDtoList = skuInfoMap.get(skuId);
            Long spuId = productSkuDtoList.get(0).getSpuId();
            PmsProductSpuDto spu = spuMap.get(spuId);
            OrderContext.SkuInfo skuInfo = new OrderContext.SkuInfo();
            skuInfo.setSpu(spu);
            skuInfo.setMerId(merId);
            skuInfo.setPmsProductSkuDtoList(productSkuDtoList);
            Optional<Integer> countOpt = skuValue.stream().map(CreateOrderReq.CreateOrderItem::getCount).reduce(Integer::sum);
            skuInfo.setCount(countOpt.orElse(0));
            return skuInfo;
        }).collect(Collectors.toList());
    }
}
